package game.player;


import game.Constants;
import game.strategy.Strategy;
import game.strategy.StrategyALLC;
import game.strategy.StrategyALLD;
import game.strategy.StrategyJOSS;
import game.strategy.StrategyRandom;
import game.strategy.StrategyTESTER;
import game.strategy.StrategyTIT_FOR_TAT;

import java.util.Hashtable;

import sim.Simulation;

public class Player{


	/**
	 * 
	 */
	private static final long serialVersionUID = 273768776960420319L;

	private Hashtable<Integer, Integer> history = new Hashtable<Integer, Integer>();
	
	private Strategy strategy;
	
	private String containerName;
	
	private int opponentPreviousChoice;

	private int roundIndex = 0;
	
	private int numberOfRounds ;
	
	private String name;

	private int step = 1;
	
	
	public Player(String stgy_name,String name,String conName) {
	
		System.out.println(name+" has strategy of "+stgy_name);
	
		Strategy strgy;
		
		if(stgy_name != null){
			if(stgy_name.equalsIgnoreCase( Constants.STRATEGY_ALL_D )){
				strgy= new StrategyALLD(); 
				bind(strgy);
			}
			if(stgy_name.equalsIgnoreCase( Constants.STRATEGY_ALL_C )){
				strgy= new StrategyALLC(); 
				bind(strgy);
			}else if(stgy_name.equalsIgnoreCase( Constants.STRATEGY_JOSS )){
				strgy = new StrategyJOSS(); 
				bind(strgy);
			}else if(stgy_name.equalsIgnoreCase( Constants.STRATEGY_RANDOM )){
				strgy = new StrategyRandom(); 
				bind(strgy);
			}else if(stgy_name.equalsIgnoreCase( Constants.STRATEGY_TESTER )){
				strgy = new StrategyTESTER(); 
				bind(strgy);
			}else if(stgy_name.equalsIgnoreCase( Constants.STRATEGY_TIT_FOR_TAT )){
				strgy = new StrategyTIT_FOR_TAT(); 
				bind(strgy);
			}	
		}
		
		opponentPreviousChoice = Strategy.NONE;
		containerName = conName;
		this.name = name; 
//		addBehaviour(new EncounterBehavior(this));
//		addBehaviour(new ReceiveDoMoveMsg());
	//	addBehaviour(new GetOppenentPrevAction(this));
		
		
	}
	
	public String getName(){
		return name;
	}
	
	public int play(){
		 if( opponentPreviousChoice == Strategy.NONE)
			return strategy.play(Strategy.NONE, roundIndex);
		 else{
			
			 int opPrevAct = -1;
			 try{
			 opPrevAct = history.get(roundIndex-1);
			 }
			 catch(Exception ex){
				// ex.printStackTrace();
				 System.err.println("No entry for specified round index");
			 }
				 
			return strategy.play(opPrevAct, roundIndex); 
		 }
	}
	private void bind(Strategy strgy) {
		strategy = strgy;
	}
	
	public String print(int action){
		if (action == Strategy.DEFECT) return "DEFECT";
		else if (action == Strategy.COOPERATE) return "COOPERATE";
		else return "NONE";
	}
	
	public int action() {
		
		if(step ==1){
			/// get Encounter Request from local refree
	
				// reply to queryhit
	    				
				int action = play();
				if( !(action == Strategy.COOPERATE || action == Strategy.DEFECT  ))
					System.err.println("no content is sent in response to Encounter request action "+action);
				
				System.out.println( getName()+ " plays "+print(action));
				//	System.err.println(forward.toString());
			
				step = 2;
				return action;
				
				

		}
		return Strategy.NONE;
	}
	public void getFeedBack(int prevAction,double score,int encounterIndex,int numOfEncounters){			
			
		if(step ==2 ){
			/// get Oppenent previous action

		
				System.out.println(" Oppenent Info Inform Message Recieved");
				opponentPreviousChoice = prevAction;
				// update history and increment round 
				roundIndex =  encounterIndex;
				numberOfRounds =  numOfEncounters ;
				history.put(roundIndex, opponentPreviousChoice );
				roundIndex++;
				
				if( roundIndex > numberOfRounds ){
					roundIndex = 0 ;
					history.clear();
				}
				
				step = 1;
		
			
		}
		
	}

	public void changeContainer(String conName){
		Simulation.output.log("Player "+getName()+" was moved from "+containerName +" to "+conName+"\n");
		containerName = conName;
	}
	public String getContainerName(){
		return containerName;
	}
	

}
